package com.hw.ble_lib;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.util.List;
import java.util.UUID;

/**
 * BLE帮助类 - 简化的蓝牙连接和通信接口
 * 
 * 使用示例:
 * <pre>
 * BleHelper bleHelper = new BleHelper(context);
 * bleHelper.setCallback(new BleCallback() {
 *     public void onConnectionStateChanged(boolean connected) {
 *         // 处理连接状态
 *     }
 *     public void onChessMoveReceived(ChessMove move) {
 *         // 处理棋子移动
 *     }
 *     // ... 其他回调
 * });
 * 
 * // 连接设备
 * bleHelper.connect("XX:XX:XX:XX:XX:XX");
 * 
 * // 发送数据
 * bleHelper.sendData(new byte[]{0x01, 0x02});
 * 
 * // 断开连接
 * bleHelper.disconnect();
 * </pre>
 */
public class BleHelper {
    
    private static final String TAG = "BleHelper";
    private static final UUID CCCD_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
    
    private final Context context;
    private final Handler mainHandler;
    private BluetoothAdapter bluetoothAdapter;
    private BluetoothGatt bluetoothGatt;
    private BluetoothGattCharacteristic writeCharacteristic;
    private BleCallback callback;
    
    private boolean isConnected = false;
    private int requestedMtu = 27; // 默认MTU为27
    
    public BleHelper(Context context) {
        this.context = context.getApplicationContext();
        this.mainHandler = new Handler(Looper.getMainLooper());
        
        BluetoothManager bluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        if (bluetoothManager != null) {
            bluetoothAdapter = bluetoothManager.getAdapter();
        }
    }

    
    private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                isConnected = true;
                Log.i(TAG, "设备已连接");
                notifyConnectionState(true);
                
                // 请求MTU（如果设置了）
                if (requestedMtu > 23) {
                    try {
                        gatt.requestMtu(requestedMtu);
                    } catch (SecurityException e) {
                        Log.e(TAG, "请求MTU权限异常", e);
                        discoverServices(gatt);
                    }
                } else {
                    discoverServices(gatt);
                }
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                isConnected = false;
                Log.i(TAG, "设备已断开");
                notifyConnectionState(false);
            }
        }

        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            Log.i(TAG, "MTU: " + mtu);
            discoverServices(gatt);
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.i(TAG, "服务发现成功");
                findCharacteristics(gatt);
            } else {
                notifyError("服务发现失败");
            }
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            byte[] data = characteristic.getValue();
            if (data != null && data.length > 0) {
                handleReceivedData(data);
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            boolean success = (status == BluetoothGatt.GATT_SUCCESS);
            notifyDataSent(success);
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.i(TAG, "通知订阅成功");
            }
        }
    };
    
    private void discoverServices(BluetoothGatt gatt) {
        try {
            gatt.discoverServices();
        } catch (SecurityException e) {
            Log.e(TAG, "发现服务权限异常", e);
            notifyError("权限不足");
        }
    }
    
    private void findCharacteristics(BluetoothGatt gatt) {
        writeCharacteristic = null;
        
        for (BluetoothGattService service : gatt.getServices()) {
            for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
                int properties = characteristic.getProperties();
                
                // 订阅通知
                if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0 ||
                    (properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
                    enableNotification(gatt, characteristic);
                }
                
                // 查找可写特征
                if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE) != 0 ||
                    (properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0) {
                    if (writeCharacteristic == null) {
                        writeCharacteristic = characteristic;
                        Log.i(TAG, "找到可写特征: " + characteristic.getUuid());
                    }
                }
            }
        }
    }
    
    private void enableNotification(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        try {
            gatt.setCharacteristicNotification(characteristic, true);
            
            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CCCD_UUID);
            if (descriptor != null) {
                int properties = characteristic.getProperties();
                if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) != 0) {
                    descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
                } else {
                    descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                }
                gatt.writeDescriptor(descriptor);
            }
        } catch (SecurityException e) {
            Log.e(TAG, "启用通知权限异常", e);
        }
    }
    
    private void handleReceivedData(byte[] data) {
        // 通知原始数据
        notifyDataReceived(data);
        
        // 尝试解析棋子移动数据
        ChessMove chessMove = parseChessMove(data);
        notifyChessMoveReceived(chessMove);
    }
    
    private ChessMove parseChessMove(byte[] data) {
        if (data == null || data.length < 6) {
            return null;
        }
        
        // 检查包头
        if (data[0] != (byte) 0xA0) {
            return null;
        }
        
        int fromX = data[1] & 0xFF;
        int fromY = data[2] & 0xFF;
        int toX = data[3] & 0xFF;
        int toY = data[4] & 0xFF;
        int pieceId = data[5] & 0xFF;
        
        // 验证数据范围
        if (fromX > 7 || fromY > 7 || toX > 7 || toY > 7 || pieceId < 1 || pieceId > 32) {
            return null;
        }
        
        return new ChessMove(fromX, fromY, toX, toY, pieceId);
    }

    
    // ==================== 公共API ====================
    
    /**
     * 设置回调接口
     */
    public void setCallback(BleCallback callback) {
        this.callback = callback;
    }
    
    /**
     * 设置MTU大小（可选，范围23-517）
     * 必须在连接前调用
     */
    public void setMtu(int mtu) {
        if (mtu >= 23 && mtu <= 517) {
            this.requestedMtu = mtu;
        }
    }
    
    /**
     * 连接蓝牙设备
     * @param address 设备MAC地址，格式: "XX:XX:XX:XX:XX:XX"
     * @return true=开始连接, false=连接失败
     */
    public boolean connect(String address) {
        if (bluetoothAdapter == null) {
            notifyError("蓝牙适配器不可用");
            return false;
        }
        
        if (address == null || address.isEmpty()) {
            notifyError("设备地址无效");
            return false;
        }
        
        try {
            BluetoothDevice device = bluetoothAdapter.getRemoteDevice(address);
            bluetoothGatt = device.connectGatt(context, false, gattCallback, BluetoothDevice.TRANSPORT_LE);
            Log.i(TAG, "开始连接: " + address);
            return true;
        } catch (Exception e) {
            Log.e(TAG, "连接失败", e);
            notifyError("连接失败: " + e.getMessage());
            return false;
        }
    }
    
    /**
     * 断开连接
     */
    public void disconnect() {
        if (bluetoothGatt != null) {
            try {
                bluetoothGatt.disconnect();
                bluetoothGatt.close();
            } catch (SecurityException e) {
                Log.e(TAG, "断开连接权限异常", e);
            }
            bluetoothGatt = null;
        }
        writeCharacteristic = null;
        isConnected = false;
    }
    
    /**
     * 发送数据
     * @param data 要发送的字节数组
     * @return true=发送请求已提交, false=发送失败
     */
    public boolean sendData(byte[] data) {
        if (!isConnected || bluetoothGatt == null) {
            notifyError("设备未连接");
            return false;
        }
        
        if (writeCharacteristic == null) {
            notifyError("未找到可写特征");
            return false;
        }
        
        if (data == null || data.length == 0) {
            notifyError("数据为空");
            return false;
        }
        
        try {
            writeCharacteristic.setValue(data);
            
            int properties = writeCharacteristic.getProperties();
            if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) != 0) {
                writeCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
            } else {
                writeCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
            }
            
            boolean result = bluetoothGatt.writeCharacteristic(writeCharacteristic);
            Log.i(TAG, "发送数据: " + bytesToHex(data) + " - " + (result ? "已提交" : "提交失败"));
            return result;
        } catch (SecurityException e) {
            Log.e(TAG, "发送数据权限异常", e);
            notifyError("权限不足");
            return false;
        }
    }
    
    /**
     * 发送HEX字符串数据
     * @param hexString HEX字符串，如 "01 02 A0 FF" 或 "0102A0FF"
     * @return true=发送成功, false=发送失败
     */
    public boolean sendHexString(String hexString) {
        byte[] data = hexStringToBytes(hexString);
        if (data == null) {
            notifyError("HEX格式错误");
            return false;
        }
        return sendData(data);
    }
    
    /**
     * 检查是否已连接
     */
    public boolean isConnected() {
        return isConnected;
    }
    
    /**
     * 释放资源
     */
    public void release() {
        disconnect();
        callback = null;
    }
    
    // ==================== 内部方法 ====================
    
    private void notifyConnectionState(boolean connected) {
        if (callback != null) {
            mainHandler.post(() -> callback.onConnectionStateChanged(connected));
        }
    }
    
    private void notifyDataReceived(byte[] data) {
        if (callback != null) {
            mainHandler.post(() -> callback.onDataReceived(data));
        }
    }
    
    private void notifyChessMoveReceived(ChessMove chessMove) {
        if (callback != null) {
            mainHandler.post(() -> callback.onChessMoveReceived(chessMove));
        }
    }
    
    private void notifyDataSent(boolean success) {
        if (callback != null) {
            mainHandler.post(() -> callback.onDataSent(success));
        }
    }
    
    private void notifyError(String error) {
        Log.e(TAG, error);
        if (callback != null) {
            mainHandler.post(() -> callback.onError(error));
        }
    }
    
    private byte[] hexStringToBytes(String hexString) {
        try {
            hexString = hexString.replaceAll("[\\s,;:-]", "");
            if (hexString.length() % 2 != 0) {
                return null;
            }
            byte[] bytes = new byte[hexString.length() / 2];
            for (int i = 0; i < bytes.length; i++) {
                bytes[i] = (byte) Integer.parseInt(hexString.substring(i * 2, i * 2 + 2), 16);
            }
            return bytes;
        } catch (NumberFormatException e) {
            return null;
        }
    }
    
    private String bytesToHex(byte[] bytes) {
        if (bytes == null) return "null";
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString().trim();
    }
}
